
/**
 * 
 */

/**
 * @author arpitagarwal
 * Copyright 2012, held by Arpit Agarwal, of University of Illinois at Urbana-Champaign. 
 */

package runner;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Hashtable;

import server.MultiThreadedServer;
import server.WorkerRunnable;
import client.Client;

public class RunSystem {

	private Hashtable<Integer, String> hashtable = new Hashtable<Integer, String>();
	private static final int PORT = 20000; 
	private static String IPAddressLeft; // = "localhost";
	private static String IPAddressRight; // = "localhost";
	private static String FILE_HASHTABLE;
	private static final String FILE_LIST_MACHINES_OF_DISSYS = "listMachines.txt"; 
	Client leftClient; 
    Client rightClient; 
    private int getServerPort() {
    	return PORT; 
    }
    private String getIPAddressLeft() {
		return IPAddressLeft;
	}
	private String getIPAddressRight() {
		return IPAddressRight;
	}
	private void setIPAddressLeft(String iPAddressLeft) {
		IPAddressLeft = iPAddressLeft;
	}
	private void setIPAddressRight(String iPAddressRight) {
		IPAddressRight = iPAddressRight;
	}
	
	public static final void systemWait(long args) {
		try {
			Thread.sleep(args);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
	}

	public void loadHashtableFromFile(String filename) {
		try {
			String line;
			FileInputStream inFile = new FileInputStream(filename);
			DataInputStream data = new DataInputStream(inFile);
			BufferedReader br = new BufferedReader(new InputStreamReader(data));
			while ((line = br.readLine()) != null) {
				hashtable.put(Integer.parseInt(line.split("-")[0]), line.split("-")[1]); 
			}
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public static void main(String [] args) {
		MultiThreadedServer serverObject = new MultiThreadedServer(PORT);
		RunSystem objectRunner = new RunSystem();
		Thread serverThread = new Thread(serverObject); 
		serverThread.start();
		String filename = FILE_HASHTABLE; 
//		objectRunner.loadHashtableFromFile(filename); 
		
		systemWait(1000);
		
         
        objectRunner.setIPAddresses("localhost", "localhost"); 
        objectRunner.leftClient = new Client(objectRunner.getIPAddressLeft(), objectRunner.getServerPort());
        objectRunner.rightClient = new Client(objectRunner.getIPAddressRight(), objectRunner.getServerPort());
        while(true) {
        	objectRunner.sendAliveMessage();
        	for (WorkerRunnable workerObject : serverObject.workerList) {
        		if (workerObject.getMessageReceived().length() > 5) {
        			String messageReceived = workerObject.getMessageReceived(); 
        			System.out.println("Message Received: " + messageReceived);
        			objectRunner.processMessage(messageReceived); 
				}
			}
        }
	}
	
	public void processMessage(String messageCombined) {
		String[] messageReceived = messageCombined.split(";");
		for (String message : messageReceived) {
			Message encodedMessage = new Message(message);
			String messageToBeSent = encodedMessage.analyzeMessage(this.hashtable);
			if (encodedMessage.getCode().equalsIgnoreCase("machineInsert")) {
				if (!leftClient.isConnectionDead() && !rightClient.isConnectionDead()) {
					String rightIP = rightClient.getIpAddress(); 
					int rightPort = rightClient.getPort(); //encodedMessage.createConnectionNewMachineMessage()
					rightClient.sendData("Right:" + encodedMessage.createConnectionNewMachineMessage()); 
					rightClient = new Client(encodedMessage.getSourceIP(), encodedMessage.getSourcePort());
					encodedMessage.setDestination(rightIP + "-" + rightPort); 
					rightClient.sendData("Right:" + messageToBeSent); 
				}
			} else if (encodedMessage.getCode().equalsIgnoreCase("ConnectRight")) {
				if (rightClient.isConnectionDead()) {
					rightClient = new Client(encodedMessage.getDestinationIP(), encodedMessage.getDestinationPort());
					encodedMessage.clearMessage(); 
					rightClient.sendData("Right:" + messageToBeSent); 
				}
			} else if (encodedMessage.getCode().equalsIgnoreCase("reconnect_left_dead")) {
				//Message.getMyIP() + ":" + "decideDestination" + ":" + 
				//"noKey:noValue:" + System.currentTimeMillis() + ":1:noMessage";
				ArrayList<String> listMachines = getListMachinesDisSys(FILE_LIST_MACHINES_OF_DISSYS); 
				for (String destination : listMachines) {
					Client tempClient = new Client(destination.split("-")[0], Integer.parseInt(destination.split("-")[1]));
					if (tempClient.isServerAvail) {
						tempClient.destroyConnection(); 
						leftClient = new Client(tempClient.getIpAddress(), tempClient.getPort()); 
					}
				}
			} else {
				this.sendAliveMessage(messageToBeSent);
			}
		}
	}
	
	public ArrayList<String> getListMachinesDisSys(String filename) {
		ArrayList<String> machinesNames = new ArrayList<String>();
		try {
			String line;
			FileInputStream inFile = new FileInputStream(filename);
			DataInputStream data = new DataInputStream(inFile); 
			BufferedReader br = new BufferedReader(new InputStreamReader(data));
			while ((line = br.readLine()) != null) {
				machinesNames.add(line); 
			}
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
		return machinesNames; 
	}
	
	public void sendAliveMessage(String messagetoSend) {
		leftClient.sendData("Left:" + messagetoSend);
//		leftClient.sendData("Right:" + messagetoSend);
//		rightClient.sendData("Left:" + messagetoSend);
		rightClient.sendData("Right:" + messagetoSend);
		try {
			Thread.sleep(100);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
	public void sendAliveMessage() {
		String message = "Left: Hello server. How are you doing?";
		String message2 = "Right: Hello server. How are you doing? I am client2";
		leftClient.sendData(message);
//		leftClient.sendData(message2);
//		rightClient.sendData(message);
		rightClient.sendData(message2);
		try {
			Thread.sleep(100);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	public void setIPAddresses(String iPAddressLeft, String iPAddressRight) {
	    setIPAddressLeft(iPAddressLeft); 
	    setIPAddressRight(iPAddressRight); 
    }

}
